﻿#include "opengl_lines6.h"

OpenGL_Lines6::OpenGL_Lines6(QOpenGLWindow *parent)
    : QOpenGLWindow(QOpenGLWindow::NoPartialUpdate, parent),
      time(nullptr), shaderProgram(nullptr), originPosX(nullptr), originPosY(nullptr),
      pointsAmount(0), color(0)
{
    qDebug() << "Type: OpenGL with temp array";
    count = 0;
    time = new QElapsedTimer();
    time->start();
    initializeOriginArraies(5000);
    this->setSurfaceType(QWindow::OpenGLSurface);
}

OpenGL_Lines6::~OpenGL_Lines6()
{
    delete time;
    delete shaderProgram;
    delete []originPosX;
    delete []originPosY;
    delete []tempx;
    delete []tempy;
}

void OpenGL_Lines6::initializeGL()
{
    initializeOpenGLFunctions();
    shaderProgram = new QOpenGLShaderProgram(this);
    shaderProgram->addCacheableShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shader/Shader/vShader.vsh");
    shaderProgram->addCacheableShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shader/Shader/fragShader.fsh");
    shaderProgram->link();
    shaderProgram->bind();
}

void OpenGL_Lines6::resizeGL(int w, int h)
{
    glViewport(0, 0, w, h);
}

void OpenGL_Lines6::paintGL()
{
    QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
    f->glClearColor(0.0, 0.0, 0.0, 1.0);
    f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    shaderProgram->bind();
    color = shaderProgram->uniformLocation("currentColor");
    lineColor = QVector4D(1.0, 1.0, 0.0, 1.0);
    shaderProgram->setUniformValue(color, lineColor);

    time->restart();
    xposAttri = shaderProgram->attributeLocation("xPos");
    yposAttri = shaderProgram->attributeLocation("yPos");
    GLfloat *xpos = new GLfloat[pointsAmount];
    GLfloat *ypos = new GLfloat[pointsAmount];
    GLfloat *tempX = xpos;
    GLfloat *tempY = ypos;
    for(int i = 0; i < pointsAmount; i++) {
        *tempX = tempx[i];
        int temp = i % 1000;
        if(temp < 250) {
            *tempY = tempy[250 - temp];
        } else if(temp >= 250 && temp < 750) {
            *tempY = tempy[temp - 250];
        } else if(temp >= 750 && temp < 1000) {
            *tempY = tempy[1250 - temp];
        }
        tempX++;
        tempY++;
    }
    shaderProgram->setAttributeArray(xposAttri, xpos, 1);
    shaderProgram->enableAttributeArray(xposAttri);
    shaderProgram->setAttributeArray(yposAttri, ypos, 1);
    shaderProgram->enableAttributeArray(yposAttri);
    glDrawArrays(GL_LINE_STRIP, 0, pointsAmount);
    shaderProgram->disableAttributeArray(xposAttri);
    shaderProgram->disableAttributeArray(yposAttri);
    qDebug() << time->nsecsElapsed();

    delete []xpos;
    delete []ypos;

    count++;
    this->setTitle(QString::number(count));
}

void OpenGL_Lines6::initializeOriginArraies(int num)
{
    pointsAmount = num;
    if(pointsAmount <= 0) {
        qDebug() << "Input Invalid";
        return;
    }
    else {
        time->restart();
        originPosX = new qreal[pointsAmount];
        originPosY = new qreal[pointsAmount];
        qreal *tempX = originPosX;
        qreal *tempY = originPosY;
        for(int i = 0; i < pointsAmount; i++) {
            *tempX = i;
            *tempY = qSin(M_PI / 500 * i);
            tempX++;
            tempY++;
        }
        tempx = new GLfloat[pointsAmount];
        tempy = new GLfloat[501];
        GLfloat *tx = tempx;
        GLfloat *ty = tempy;
        int trap = pointsAmount - 1;
        for(int i = 0; i < pointsAmount; i++) {
            *tx = (GLfloat)i * 2 / trap - 1;
            tx++;
        }
        for(int i = 250; i <= 750; i++) {
            *ty = (GLfloat)qSin(M_PI / 500 * i) * 0.8;
            ty++;
        }
        qDebug() << "Init Time:" << time->nsecsElapsed() << "ns";
    }
}
